package com.example.mytestdemo.customviewbook

import android.animation.PropertyValuesHolder
import android.animation.ValueAnimator
import android.animation.ValueAnimator.AnimatorUpdateListener
import android.content.Context
import android.graphics.Camera
import android.graphics.Canvas
import android.graphics.Matrix
import android.util.AttributeSet
import android.util.Log
import android.view.MotionEvent
import android.view.animation.BounceInterpolator
import android.widget.LinearLayout

/**
 * @author tgw
 * @date 2023/2/3
 * @describe
 */

class ClockViewGroup @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0,
) : LinearLayout(context, attrs, defStyleAttr) {
    private val MAX_ROTATE_DEGREE = 20f
    private var mCenterX: Float = 0.0f
    private var mCenterY: Float = 0.0f
    private var mCanvasRotationX: Float = 0.0f
    private var mCanvasRotationY: Float = 0.0f
    private var mMatrixCanvas: Matrix = Matrix()
    private var mCamera: Camera = Camera()


    private var mSteadyAnim: ValueAnimator? = null


    override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
        super.onSizeChanged(w, h, oldw, oldh)
        mCenterX = (w / 2).toFloat()
        mCenterY = (h / 2).toFloat()
        Log.d("TAG", "onSizeChanged: mCenterX:$mCenterX----mCenterY:$mCenterY")
        Log.d("TAG", "onSizeChanged: getwidth:$w---gethjeight:$h")

    }

    override fun dispatchDraw(canvas: Canvas) {
        Log.d("TAG", "dispatchDraw: mCenterX:$mCenterX---mCenterY:$mCenterY")
        //重置图像
        mMatrixCanvas.reset()
        mCamera.save()
        mCamera.rotateX(mCanvasRotationX)
        mCamera.rotateY(mCanvasRotationY)
        mCamera.getMatrix(mMatrixCanvas)
        mCamera.restore()

        //将中心点移动到图像中心点
        mMatrixCanvas.preTranslate(-mCenterX, -mCenterY)
        mMatrixCanvas.postTranslate(mCenterX, mCenterY)

        canvas.save()
        canvas.setMatrix(mMatrixCanvas)
        super.dispatchDraw(canvas)
        canvas.restore()

        //方式2，见1.1.2章节介绍，方式二
//        mMatrixCanvas.reset()
//        mCamera.save()
//        mCamera.rotateX(mCanvasRotationX)
//        mCamera.rotateY(mCanvasRotationY)
//        mCamera.applyToCanvas(canvas)
//        mCamera.restore()
//
//        //将中心点移动到图像中心点
//        mMatrixCanvas.preTranslate(-mCenterX,-mCenterY)
//        mMatrixCanvas.postTranslate(mCenterX,mCenterY)
//
//
//        super.dispatchDraw(canvas)
//        canvas.restore()
    }

    //返回true才会有ACTION_MOVE ACTION_UP后续消费被接收
    //坐标参考：https://www.jianshu.com/p/0701781573d1
    override fun onTouchEvent(event: MotionEvent): Boolean {

        var x = event.x
        var y = event.y
        when (event.actionMasked) {
            MotionEvent.ACTION_DOWN -> {
                cancelSteadyAnimIfNeed()
                rotationCanvasWhenMove(x, y)
                return true
            }
            MotionEvent.ACTION_MOVE -> {
                rotationCanvasWhenMove(x, y)
                return true
            }
            //注意移动后，如果当前组件的外层是可滑动的view，那么只会触发MotionEvent.ACTION_CANCEL，而不会触发  MotionEvent.ACTION_UP
            MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> {
                startNewSteadyAnim()
                return true
            }
        }

        return super.onTouchEvent(event)

    }

    private fun rotationCanvasWhenMove(x: Float, y: Float) {
        var dx = x - mCenterX
        var dy = y - mCenterY
        Log.d("TAG", "rotationCanvasWhenMove: getwidth:$width---gethjeight:$height")

        var percentX = dx / (width / 2)
        var percentY = dy / (height / 2)

        if (percentX > 1f) {
            percentX = 1f
        } else if (percentX < -1f) {
            percentX = -1f
        }
        if (percentY > 1f) {
            percentY = 1f
        } else if (percentY < -1f) {
            percentY = -1f
        }

        mCanvasRotationY = MAX_ROTATE_DEGREE * percentX
        mCanvasRotationX = -(MAX_ROTATE_DEGREE * percentY)

        postInvalidate()
    }

    /**
     * 补充ValueAnimator.ofPropertyValuesHolder的使用
     */
    private fun startNewSteadyAnim() {
        val propertyNameRotateX = "mCanvasRotationX"
        val propertyNameRotateY = "mCanvasRotationY"
        val holderRotateX = PropertyValuesHolder.ofFloat(propertyNameRotateX, mCanvasRotationX, 0f)
        val holderRotateY = PropertyValuesHolder.ofFloat(propertyNameRotateY, mCanvasRotationY, 0f)
        mSteadyAnim = ValueAnimator.ofPropertyValuesHolder(holderRotateX, holderRotateY)
        mSteadyAnim?.setDuration(5000)
        mSteadyAnim?.setInterpolator(BounceInterpolator())
        mSteadyAnim?.addUpdateListener(AnimatorUpdateListener { animation ->
            mCanvasRotationX = animation.getAnimatedValue(propertyNameRotateX) as Float
            mCanvasRotationY = animation.getAnimatedValue(propertyNameRotateY) as Float
            postInvalidate()
        })
        mSteadyAnim?.start()
        Log.d("TAG", "startNewSteadyAnim: ")
    }

    private fun cancelSteadyAnimIfNeed() {
        if (mSteadyAnim != null && (mSteadyAnim!!.isStarted() || mSteadyAnim!!.isRunning())) {
            mSteadyAnim?.cancel()
        }
    }
}